﻿using RXY_Mall.Application.Order.Dto;
using RXY_Mall.Core;
using RXY_Mall.Core.Tool;
using RXY_Mall.Data;
using RXY_Mall.Domain;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;

namespace RXY_Mall.Application.Return
{
    public class ReturnService : IReturnService
    {
        RXY_MallContext db = new RXY_MallContext();

        #region 退换货
        //退换货列表
        public Response<IPagedList<GetOrderReturnsOutput>> GetReturns(string return_no, string contact_mobile, string shop_name, int return_type, int return_reason, string start_date, string end_date, int return_status, int page_index = 1, int page_size = 20, int shop_id = -1)
        {
            Response<IPagedList<GetOrderReturnsOutput>> result = new Response<IPagedList<GetOrderReturnsOutput>>();
            try
            {
                List<int> lstStatus = new List<int>();
                lstStatus.Add((int)OrderStatus.Shipment);
                lstStatus.Add((int)OrderStatus.Receive);
                //lstStatus.Add((int)OrderStatus.Comment);
                lstStatus.Add((int)OrderStatus.Complete);

                var source = db.gw_returns
                    .Include(o => o.gw_return_request)
                    .Where(o => !o.deleted)
                    .Select(item => new GetOrderReturnsOutput
                    {
                        contact_mobile = item.gw_return_request.contact_mobile,
                        contact_name = item.gw_return_request.contact_name,
                        order_amount = item.order_amount,
                        refund_amount = item.refund_amount,
                        return_id = item.id,
                        return_no = item.return_no,
                        _return_reason = item.gw_return_request.return_reason,
                        _return_status = item.status,
                        _return_type = item.gw_return_request.return_type,
                        shop_name = item.gw_shop.name,
                        shop_id = item.shop_id,
                        add_time = item.add_time,
                        shipping_fee = item.shipping_fee,
                        _is_shipping_fee = item.is_shipping_fee,
                    });

                if (shop_id > -1)
                {
                    source = source.Where(s => s.shop_id == shop_id);
                }
                if (!string.IsNullOrEmpty(return_no))
                {
                    source = source.Where(s => s.return_no == return_no);
                }
                if (return_status != (int)ReturnStatus.All)
                {
                    source = source.Where(s => s._return_status == return_status);
                }
                if (return_reason != (int)ReturnReason.All)
                {
                    source = source.Where(s => s._return_reason == return_reason);
                }
                if (return_type != (int)ReturnType.All)
                {
                    source = source.Where(s => s._return_type == return_type);
                }
                if (!string.IsNullOrWhiteSpace(contact_mobile))
                {
                    source = source.Where(s => s.contact_mobile == contact_mobile);
                }
                if (!string.IsNullOrWhiteSpace(shop_name))
                {
                    source = source.Where(s => s.shop_name == shop_name);
                }
                if (!string.IsNullOrWhiteSpace(start_date))
                {
                    DateTime start;
                    if (DateTime.TryParse(start_date, out start))
                        source = source.Where(s => s.add_time > start);
                }
                if (!string.IsNullOrWhiteSpace(end_date))
                {
                    DateTime end;
                    if (DateTime.TryParse(end_date, out end))
                        source = source.Where(s => s.add_time <= end);
                }

                source = source.OrderByDescending(s => s.add_time);

                var pagelist = new PagedList<GetOrderReturnsOutput>(source, page_index, page_size);
                foreach (var item in pagelist)
                {
                    switch ((ReturnStatus)item._return_status)
                    {
                        case ReturnStatus.提交申请:
                            item.return_status = "提交申请";
                            break;
                        case ReturnStatus.审核通过:
                            item.return_status = "审核通过";
                            break;
                        case ReturnStatus.退货信息:
                            item.return_status = "退货信息";
                            break;
                        case ReturnStatus.商家已确认收货:
                            item.return_status = "商家已确认收货";
                            break;
                        case ReturnStatus.退款中:
                            item.return_status = "退款中";
                            break;
                        case ReturnStatus.商家重新发货:
                            item.return_status = "商家重新发货";
                            break;
                        case ReturnStatus.买家确认收货:
                            item.return_status = "买家确认收货";
                            break;
                        case ReturnStatus.已完成:
                            item.return_status = "已完成";
                            break;
                        case ReturnStatus.已取消:
                            item.return_status = "已取消";
                            break;
                        case ReturnStatus.审核失败:
                            item.return_status = "审核失败";
                            break;
                    }
                    switch ((ReturnReason)item._return_reason)
                    {
                        case ReturnReason.SevenDaysWithoutReason:
                            item.return_reason = "七天无理由";
                            break;
                        case ReturnReason.NoWant:
                            item.return_reason = "不想要了";
                            break;
                        case ReturnReason.NoLike:
                            item.return_reason = "不喜欢了";
                            break;
                        case ReturnReason.DescribeDiscrepancy:
                            item.return_reason = "货物与描述不符";
                            break;
                        case ReturnReason.Expire:
                            item.return_reason = "与商品描述不符";
                            break;
                        case ReturnReason.Other:
                            item.return_reason = "其他";
                            break;
                        default:
                            break;
                    }
                    switch ((ReturnType)item._return_type)
                    {
                        case ReturnType.GoodsAndMoney:
                            item.return_type = "我要退货退款";
                            break;
                        case ReturnType.Money:
                            item.return_type = "我要退款";
                            break;
                        case ReturnType.Goods:
                            item.return_type = "我要换货";
                            break;
                        default:
                            break;
                    }

                    item.is_shipping_fee = item._is_shipping_fee ? "是" : "否";


                }
                result.code = 1;
                result.data = pagelist;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
                result.msg = ex.ToString();
                result.code = 2;
            }
            return result;
        }

        //获得退换货
        public async Task<Response<GetReturnOutput>> GetReturn(int return_id, int shop_id = 0)
        {
            Response<GetReturnOutput> result = new Response<GetReturnOutput>();
            try
            {
                var order = await db.gw_returns
                    .Include(r => r.gw_order)
                    .Include(r => r.gw_return_request)
                    .Include(r => r.gw_return_request.gw_return_request_picture)
                    .Include(o => o.gw_return_goods)
                    .Include(o => o.gw_return_goods.gw_goods.gw_shop)
                    .Include(o => o.gw_return_audit)
                    .Include(o => o.gw_return_waybill)
                    .Where(o => o.id == return_id)
                    .Select(item => new GetReturnOutput()
                    {
                        add_time = item.add_time,
                        return_no = item.return_no,
                        order_no = item.gw_order.order_no,
                        order_id = item.order_id,
                        contact_mobile = item.gw_return_request.contact_mobile,
                        contact_name = item.gw_return_request.contact_name,
                        order_amount = item.order_amount,
                        refund_amount = item.refund_amount,
                        return_id = item.id,
                        _return_reason = item.gw_return_request.return_reason,
                        _return_status = item.status,
                        _return_type = item.gw_return_request.return_type,
                        shop_name = item.gw_shop.name,
                        complete_time = item.complete_time,
                        cancel_time = item.cancel_time,
                        audit_fail_time = item.audit_fail_time,
                        audit_pass_time = item.audit_pass_time,
                        expire_time = item.expire_time,
                        shop_receive_time = item.shop_receive_time,
                        shop_shipment_time = item.shop_shipment_time,
                        shop_refund_time = item.shop_refund_time,
                        user_receive_time = item.user_receive_time,
                        user_shipment_time = item.user_shipment_time,
                        shipping_fee = item.shipping_fee,
                        _is_shipping_fee = item.is_shipping_fee,

                        buyer_waybill = item.gw_return_waybill.Where(w => w.sender_type == 1)
                        .Select(w => new Waybill()
                        {
                            add_time = w.add_time,
                            company_name = w.company_name,
                            telphone = w.telphone,
                            waybill_no = w.waybill_no,
                        }).FirstOrDefault(),

                        merchant_waybill = item.gw_return_waybill.Where(w => w.sender_type == 2)
                        .Select(w => new Waybill()
                        {
                            add_time = w.add_time,
                            company_name = w.company_name,
                            telphone = w.telphone,
                            waybill_no = w.waybill_no,
                        }).FirstOrDefault(),

                        goods = new OrderGoods()
                        {
                            category_id = (int)item.gw_return_goods.gw_goods.category_id,

                            goods_id = item.gw_return_goods.goods_id,
                            goods_name = item.gw_return_goods.goods_name,
                            goods_type = (GoodsType)item.gw_return_goods.goods_type,
                            json_specs = item.gw_return_goods.sku_specs,

                            buy_type = (BuyType)item.gw_return_goods.buy_type,
                            goods_quantity = item.gw_return_goods.quantity,
                            goods_price = item.gw_return_goods.pay_price,
                            picture_url = item.gw_return_goods.picture_url,
                        },


                        shop = new ShopOutput()
                        {
                            shop_id = item.gw_return_goods.gw_goods.gw_shop.id,
                            shop_logo = item.gw_return_goods.gw_goods.gw_shop.logo,
                            shop_name = item.gw_return_goods.gw_goods.gw_shop.name,
                        },

                        request = new ReturnRequest()
                        {
                            contact_mobile = item.gw_return_request.contact_mobile,
                            contact_name = item.gw_return_request.contact_name,
                            remark = item.gw_return_request.remark,
                            return_reason = (ReturnReason)item.gw_return_request.return_reason,
                            return_type = (ReturnType)item.gw_return_request.return_type,
                            pictures = item.gw_return_request.gw_return_request_picture.OrderBy(p => p.sort).Select(p => p.url).ToList(),
                        },

                        gw_return_audit = item.gw_return_audit,

                    })
                    .FirstOrDefaultAsync();

                if (order == null)
                {
                    result.msg = "服务单不存在";
                    return result;
                }

                if (shop_id != 0)
                {
                    if (shop_id != order.shop.shop_id)
                    {
                        result.msg = "权限不足";
                        return result;
                    }
                }

                if (order.gw_return_audit != null)
                {
                    order.audit = new ReturnAudit()
                    {
                        add_time = order.gw_return_audit.add_time,
                        audit_note = order.gw_return_audit.audit_note,
                        is_pass = order.gw_return_audit.is_pass ? "通过" : "未通过",
                        remark = order.gw_return_audit.remark,
                    };
                }

                switch ((ReturnStatus)order._return_status)
                {
                    case ReturnStatus.提交申请:
                        order.return_status = "提交申请";
                        break;
                    case ReturnStatus.审核通过:
                        order.return_status = "审核通过";
                        break;
                    case ReturnStatus.退货信息:
                        order.return_status = "退货信息";
                        break;
                    case ReturnStatus.商家已确认收货:
                        order.return_status = "商家已确认收货";
                        break;
                    case ReturnStatus.退款中:
                        order.return_status = "退款中";
                        break;
                    case ReturnStatus.商家重新发货:
                        order.return_status = "商家重新发货";
                        break;
                    case ReturnStatus.买家确认收货:
                        order.return_status = "买家确认收货";
                        break;
                    case ReturnStatus.已完成:
                        order.return_status = "已完成";
                        break;
                    case ReturnStatus.已取消:
                        order.return_status = "已取消";
                        break;
                    case ReturnStatus.审核失败:
                        order.return_status = "审核失败";
                        break;
                    default:
                        break;
                }

                switch ((ReturnReason)order._return_reason)
                {
                    case ReturnReason.SevenDaysWithoutReason:
                        order.return_reason = "七天无理由";
                        break;
                    case ReturnReason.NoWant:
                        order.return_reason = "不想要了";
                        break;
                    case ReturnReason.NoLike:
                        order.return_reason = "不喜欢了";
                        break;
                    case ReturnReason.DescribeDiscrepancy:
                        order.return_reason = "货物与描述不符";
                        break;
                    case ReturnReason.Expire:
                        order.return_reason = "与商品描述不符";
                        break;
                    case ReturnReason.Other:
                        order.return_reason = "其他";
                        break;
                    default:
                        break;
                }

                switch ((ReturnType)order._return_type)
                {
                    case ReturnType.GoodsAndMoney:
                        order.return_type = "我要退货退款";
                        break;
                    case ReturnType.Money:
                        order.return_type = "我要退款";
                        break;
                    case ReturnType.Goods:
                        order.return_type = "我要换货";
                        break;
                    default:
                        break;
                }

                order.is_shipping_fee = order._is_shipping_fee ? "是" : "否";


                result.code = 1;
                result.data = order;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
                result.msg = ex.ToString();
                result.code = 2;
            }
            return result;
        }

        //审核
        public async Task<Response<bool>> UpdateReturnAudit(UpdateReturnAuditInput input)
        {
            var result = new Response<bool>();
            result.data = false;
            try
            {
                var service = await db.gw_returns
                    .Include(o => o.gw_return_audit)
                    .FirstOrDefaultAsync(o => o.id == input.return_id);

                if (input.shop_id != 0)
                {
                    if (input.shop_id != service.shop_id)
                    {
                        result.msg = "没有权限";
                        return result;
                    }
                }

                if (service.gw_return_audit != null)
                {
                    service.gw_return_audit.add_time = DateTime.Now;
                    service.gw_return_audit.auditor_id = 1;
                    service.gw_return_audit.audit_note = input.audit_note;
                    service.gw_return_audit.remark = input.audit_remark;
                    service.gw_return_audit.is_pass = input.is_pass == 1 ? true : false;
                    db.Entry(service.gw_return_audit).Property(w => w.add_time).IsModified = true;
                    db.Entry(service.gw_return_audit).Property(w => w.auditor_id).IsModified = true;
                    db.Entry(service.gw_return_audit).Property(w => w.audit_note).IsModified = true;
                    db.Entry(service.gw_return_audit).Property(w => w.remark).IsModified = true;
                    db.Entry(service.gw_return_audit).Property(w => w.is_pass).IsModified = true;
                }
                else
                {
                    service.gw_return_audit = new gw_return_audit()
                    {
                        add_time = DateTime.Now,
                        auditor_id = 1,
                        audit_note = input.audit_note,
                        remark = input.audit_remark,
                        is_pass = input.is_pass == 1 ? true : false,
                    };
                    db.gw_return_audits.Add(service.gw_return_audit);
                }

                var order = await db.gw_orders.FindAsync(service.order_id);
                if (input.is_pass == 1)
                {
                    service.status = (int)ReturnStatus.审核通过;
                    service.audit_pass_time = DateTime.Now;
                    service.is_shipping_fee = input.is_shipping_fee == 1 ? true : false;
                    service.shipping_fee = order.shipping_fee;
                    db.Entry(service).Property(w => w.is_shipping_fee).IsModified = true;
                    db.Entry(service).Property(w => w.shipping_fee).IsModified = true;
                }
                else
                {
                    service.status = (int)ReturnStatus.审核失败;
                    service.audit_fail_time = DateTime.Now;
                    service.cancel_time = DateTime.Now;
                    db.Entry(service).Property(w => w.cancel_time).IsModified = true;

                    if (order != null)
                    {
                        order.service_status = (byte)ServiceStatus.可申请售后;
                        if (order.service_expire_time < DateTime.Now)
                        {
                            order.service_expire_time = DateTime.Now.AddDays(1);
                        }
                    }
                }
                db.Entry(service).Property(w => w.status).IsModified = true;
                db.Entry(service).Property(w => w.audit_pass_time).IsModified = true;

                await db.SaveChangesAsync();
                result.code = 1;
                result.msg = "保存成功";
                result.data = true;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
                result.msg = ex.ToString();
                result.code = 2;
            }
            return result;
        }

        //退款
        public async Task<Response<bool>> UpdateReturnRefund(UpdateReturnRefundInput input)
        {
            var result = new Response<bool>();
            try
            {
                var service = await db.gw_returns
                    .Include(r => r.gw_user.gw_finance_property)
                    .Include(r => r.gw_shop.gw_shop_property)
                    .Include(r => r.gw_order)
                    .Include(r => r.gw_order.gw_order_goods)
                    //.Include(r => r.gw_order.gw_order_goods.gw_goods.gw_shop)
                    .FirstOrDefaultAsync(o => o.id == input.return_id);

                if (input.shop_id != 0)
                {
                    if (input.shop_id != service.shop_id)
                    {
                        result.msg = "权限不足";
                        return result;
                    }
                }

                if (service.refund_amount != null && service.shop_refund_time != null)
                {
                    result.msg = "已退款";
                    return result;
                }
                var pay_no = Utils.GetOrderNumber();
                var error = "";

                if (!RefundOrder(service.gw_order, pay_no, out error))
                {
                    result.msg = error;
                    return result;
                }
                else
                {
                    LogHelper.WriteLog(string.Format("订单号:{0},退款成功！", service.gw_order.order_no));
                }

                //退款结算 TODO:
                //余额足够：财务添加扣款记录gw_shop_finance_log
                //余额不足：添加结算gw_shop_finance_settlement，添加冻结/欠款gw_shop_finance_return
                var gw_shop_finance_settlement = new gw_shop_finance_settlement()
                {
                    add_time = DateTime.Now,
                    //account_period = service.gw_order.gw_order_goods.gw_goods.gw_shop.account_period,
                    money = 0,
                    order_id = service.gw_order.id,
                    order_no = service.gw_order.order_no,
                    order_total = service.gw_order.goods_total,
                    //goods_type = (byte)service.gw_order.gw_order_goods.goods_type,
                    //service_rate = service.gw_order.gw_order_goods.service_rate,
                    //shop_id = service.gw_order.gw_order_goods.shop_id,
                    type = 2,
                    status = 4,
                    settlement_no = "FS" + DateTime.Now.ToString("yyMMddHHmmss") + RandomHelper.CreateRandomValue(6),
                };
                //gw_shop_finance_settlement.money = service.gw_order.gw_order_goods.settlement_price == null ? 0 : (decimal)service.gw_order.gw_order_goods.settlement_price * service.gw_order.gw_order_goods.quantity;
                //if (gw_shop_finance_settlement.goods_type == 1 && (service.gw_order.gw_order_goods.settlement_price == null || service.gw_order.gw_order_goods.settlement_price <= 0))
                //{
                //    var money = service.gw_order.gw_order_goods.pay_price * service.gw_order.gw_order_goods.quantity * (1 - service.gw_order.gw_order_goods.service_rate / 100);
                //    money = Math.Round(money, 2, MidpointRounding.AwayFromZero);
                //    gw_shop_finance_settlement.money = money;
                //}
                //var money = service.gw_order.gw_order_goods.pay_price * service.gw_order.gw_order_goods.quantity * (1 - service.gw_order.gw_order_goods.service_rate / 100);
                //money = Math.Round(money, 2, MidpointRounding.AwayFromZero);
                //gw_shop_finance_settlement.money = money;
                //if ((gw_shop_finance_settlement.goods_type == 2|| gw_shop_finance_settlement.goods_type == 3) && service.gw_order.gw_order_goods.settlement_price != null && service.gw_order.gw_order_goods.settlement_price > 0)
                //{
                //    gw_shop_finance_settlement.money = (decimal)service.gw_order.gw_order_goods.settlement_price * service.gw_order.gw_order_goods.quantity;
                //}
                db.gw_shop_finance_settlements.Add(gw_shop_finance_settlement);

                //优惠券退回
                if (service.gw_order.user_coupon_id > 0)
                {
                    var coupon = await db.gw_user_coupons.FindAsync(service.gw_order.user_coupon_id);
                    if (coupon != null)
                    {
                        coupon.status = 1;
                        db.Entry(coupon).Property(o => o.status).IsModified = true;
                    }
                }

                //退款
                service.refund_amount = service.order_amount;
                if (!service.is_shipping_fee)
                {
                    service.refund_amount -= service.shipping_fee;
                }

                //用户退款
                service.gw_user.gw_finance_property.balance += (decimal)service.refund_amount;
                db.Entry(service.gw_user.gw_finance_property).Property(o => o.balance).IsModified = true;

                //用户余额消息
                gw_finance_property_log finance_property_log = new gw_finance_property_log()
                {
                    add_time = DateTime.Now,
                    currency = 1,
                    last_value = service.gw_user.gw_finance_property.balance,
                    order_no = service.gw_order.order_no,
                    remark = TradeType.申请退款.ToString(),
                    trade_type = (int)TradeType.申请退款,
                    type = (int)PaymentType.Income,
                    user_id = service.gw_user.id,
                    value = (decimal)service.refund_amount,
                };
                db.gw_finance_property_logs.Add(finance_property_log);

                
                service.shop_refund_time = DateTime.Now;
                service.complete_time = DateTime.Now;
                service.status = (int)ReturnStatus.已完成;

                db.Entry(service).Property(w => w.refund_amount).IsModified = true;
                db.Entry(service).Property(w => w.shop_refund_time).IsModified = true;
                db.Entry(service).Property(w => w.complete_time).IsModified = true;
                db.Entry(service).Property(w => w.status).IsModified = true;

                service.gw_order.service_status = (byte)ServiceStatus.售后关闭;
                db.Entry(service.gw_order).Property(w => w.service_status).IsModified = true;
                await db.SaveChangesAsync();

                result.code = 1;
                result.msg = "保存成功";
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
                result.msg = ex.ToString();
                result.code = 2;
            }
            return result;
        }

        //商家发货
        public async Task<Response<bool>> UpdateReturnShipment(UpdateReturnShipmentInput input)
        {
            var result = new Response<bool>();
            try
            {
                var service = await db.gw_returns
                    //.Include(o => o.gw_order)
                    .Include(o => o.gw_return_waybill)
                    .FirstOrDefaultAsync(o => o.id == input.return_id);

                if (input.shop_id != 0)
                {
                    if (input.shop_id != service.shop_id)
                    {
                        result.msg = "权限不足";
                        return result;
                    }
                }

                var gw_return_waybill = service.gw_return_waybill.FirstOrDefault(w => w.sender_type == 2);
                if (gw_return_waybill != null)
                {
                    gw_return_waybill.company_name = input.logistics_name.Split(',')[0];
                    gw_return_waybill.telphone = input.logistics_name.Split(',')[1];
                    gw_return_waybill.waybill_no = input.waybill_no;
                    db.Entry(gw_return_waybill).Property(w => w.company_name).IsModified = true;
                    db.Entry(gw_return_waybill).Property(w => w.telphone).IsModified = true;
                    db.Entry(gw_return_waybill).Property(w => w.waybill_no).IsModified = true;
                }
                else
                {
                    gw_return_waybill = new gw_return_waybill()
                    {
                        company_name = input.logistics_name.Split(',')[0],
                        telphone = input.logistics_name.Split(',')[1],
                        waybill_no = input.waybill_no,
                        sender_type = 2,
                        return_id = input.return_id,
                        add_time = DateTime.Now,
                    };
                    db.gw_return_waybills.Add(gw_return_waybill);
                }
                service.status = (int)ReturnStatus.商家重新发货;
                service.shop_shipment_time = DateTime.Now;
                db.Entry(service).Property(w => w.status).IsModified = true;
                db.Entry(service).Property(w => w.shop_shipment_time).IsModified = true;

                await db.SaveChangesAsync();

                result.code = 1;
                result.msg = "保存成功";

            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
                result.msg = ex.ToString();
                result.code = 2;
            }
            return result;
        }

        /// <summary>
        /// 退款单
        /// </summary>
        /// <param name="order"></param>
        /// <param name="pay_no"></param>
        /// <param name="error"></param>
        /// <returns></returns>
        public bool RefundOrder(gw_order order, string pay_no, out string error)
        {
            error = "";
            var flag = false;
            try
            {
                var refund = db.gw_order_refunds.Find(order.id);
                if (refund != null)
                {
                    error = "订单已退款";
                    return flag;
                }
                refund = new gw_order_refund()
                {
                    add_time = DateTime.Now,
                    pay_no = pay_no,
                    pay_type = order.pay_type,
                    pay_amount = order.amount,
                    id = order.id,
                };
                db.gw_order_refunds.Add(refund);
                db.SaveChanges();
                flag = true;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
                error = "订单已退款";
            }
            return flag;
        }
        #endregion
    }
}
